/*
 * ﻿Copyright (C) 2009-2013 NewMain Softech
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
 * either express or implied. See the License for the specific language
 * governing permissions and limitations under the License.
 */
package com.newmainsoftech.gwetons.shared.timer;

import com.google.gwt.core.client.GWT;
import com.newmainsoftech.gwetons.client.timer.TimerControllerGinModule;
import com.newmainsoftech.gwetons.client.timer.TimerControllerGinjector;
import com.newmainsoftech.gwetons.shared.TargetEnvironment;
import com.newmainsoftech.gwetons.shared.logging.LoggerWrapAdapterTemplate;

/**
 * Factory for {@link TimerController} object. <br />
 * With default configuration, this will instantiate <code>TimerController</code> object for client-side;  
 * it will be instantiated by {@link TimerControllerGinModule} class (via {@link TimerControllerGinjector} 
 * class) per every call to {@link #getTimerControllerInstance()} method. (To obtain semi-singleton 
 * <code>TimerController</code> instance instead, create <code>TimerControllerGinjector</code> 
 * implementation for <code>TimerUniControllerGinModule</code> and set its instance by 
 * {@link #setTimerControllerInjector(TimerControllerInjector)} method.)<br />
 * To yield <code>TimerController</code> instance for server-side, develop custom 
 * {@link TimerControllerInjector} implementation and set it by 
 * {@link #setTimerControllerInjector(TimerControllerInjector)} method.
 * 
 * @author <a href="mailto:artymt@gmail.com">Arata Y.</a>
 */
public class TimerControllerFactoryImpl extends LoggerWrapAdapterTemplate implements TimerControllerFactory {
	
	@Override
	protected String getNameForLogging() {
		return this.getClass().getName();
	}
	
	protected TimerControllerFactoryImpl() {
	}

	private TimerControllerInjector timerControllerInjector;
		private Object timerControllerInjectorLock = new Object();
		public TimerControllerInjector getTimerControllerInjector() {
			synchronized( timerControllerInjectorLock) {
				if ( timerControllerInjector == null) {
					if ( GWT.isClient()) {
						TimerControllerGinjector ginjector = GWT.create( TimerControllerGinjector.class);
						setTimerControllerInjector( ginjector);
					}
					else {
						throw new UnsupportedOperationException( 
								"%1$s uses %2$s as default %3$s object, hence it's valid only for " 
								.concat( "JavaScript environment at client side. To use in non-JavaScript ")  
								.concat( "environment, it is necessary to inject custom %3$s instance ") 
								.concat( "created for non-JavaScript environment.")
								.replace( "%1$s", TimerControllerFactoryImpl.class.getName())
								.replace( "%2$s", TimerControllerGinjector.class.getName())
								.replace( "%3$s", TimerControllerInjector.class.getName())
								);
					}
				}
				return timerControllerInjector;
			} // synchronized
		}
		public void setTimerControllerInjector(
				TimerControllerInjector timerControllerInjector) {
			synchronized( timerControllerInjectorLock) {
				this.timerControllerInjector = timerControllerInjector;
			} // synchronized
		}

	public TimerController getTimerControllerInstance() {
		TimerController timerControllerIntf 
		= getTimerControllerInjector().getTimerController();
		
		switch( timerControllerIntf.getTargetEnvironment()) {
		case JavaScript:
			if ( !GWT.isClient()) {
				throw new UnsupportedOperationException(
						"%1$s instance being obtained via currently-set %2$s object is designed to " 
						.concat( "run only for JavaScript environment. Please set other %3$s ") 
						.concat( " instance developped for non-JavaScript or both environment.")
						.replace( "%1$s", TimerController.class.getName())
						.replace( "%2$s", TimerControllerGinjector.class.getName())
						.replace( "%3$s", TimerControllerInjector.class.getName())
						);
			}
			break;
		case NonJavaScript:
			if ( GWT.isClient()) {
				throw new UnsupportedOperationException(
						"%1$s instance being obtained via currently-set %2$s object is designed to " 
						.concat( "run only for JavaScript environment. Please set other %3$s ") 
						.concat( " instance developped for non-JavaScript or both environment.")
						.replace( "%1$s", TimerController.class.getName())
						.replace( "%2$s", TimerControllerGinjector.class.getName())
						.replace( "%3$s", TimerControllerInjector.class.getName())
						);
			}
			break;
		case Both:
			break;
		default:
			throw new UnsupportedOperationException(
					" %1$s is unrecognizable %2$s item as of when this version of %3$s class " 
					.concat( "was developped. Please report this error.")
					.replace( "%1$s", timerControllerIntf.getTargetEnvironment().name())
					.replace( "%2$s", TargetEnvironment.class.getName())
					.replace( "%3$s", TimerControllerFactoryImpl.class.getName())
					);
		} // switch
		
		return timerControllerIntf;
	}
}
